package app;

import com.google.gdata.client.appsforyourdomain.AppsGroupsService;
import com.google.gdata.data.appsforyourdomain.generic.GenericFeed;
import gui.Fenetre;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

/**
 *
 * @author alexisl
 */
public class Application {

    private AppsGroupsService myService;
    private ArrayList<Groupe> listeGroupes;
    private ArrayList<Groupe> listeGroupesServeur;
    private Fenetre fenetre;
    private String username;
    private File fichier;
    private String currentGroupAdded;
    private String currentMemberAdded;
    private char[] password;
    private int progressMax;
    private int progressCurrent;

    public Application() {
        listeGroupes = new ArrayList<Groupe>();
        listeGroupesServeur = new ArrayList<Groupe>();
        fenetre = new Fenetre(600, 400, this);
    }

    public void addGroupe(String nom) {
        listeGroupes.add(new Groupe(nom, new ArrayList<String>()));
    }

    public void sortGroupes() {
        Collections.sort(listeGroupes, new Comparateur());

        for (int i = 0; i < listeGroupes.size(); i++) {
            Collections.sort(listeGroupes.get(i).getEmailsGroupe());
        }
    }

    public void setUsername(String user) {
        username = user;
    }

    public void setFichierPath(File file) {
        fichier = file;
    }

    public void setPassword(char[] pass) {
        password = pass;
    }

    public void setProgressDetection() {
        progressCurrent = 0;
        progressMax = 0;

        for (int i = 0; i < listeGroupes.size(); i++) {
            progressMax++;
        }
        
        for (int i = 0; i < listeGroupesServeur.size(); i++) {
            progressMax++;
        }
    }
    
    public void setProgressCreation(int membersToDeleteSize, int groupsToDeleteSize, int groupsToAddSize, int membersToaddSize) {
        progressCurrent = 0;
        progressMax = 0;
        
        progressMax += membersToDeleteSize;
        progressMax += groupsToDeleteSize;
        progressMax += groupsToAddSize;
        progressMax += membersToaddSize;
    }

    public ArrayList<Groupe> getListeGroupes() {
        return listeGroupes;
    }

    public String getCurrentGroupAdded() {
        return currentGroupAdded;
    }

    public String getCurrentMemberAdded() {
        return currentMemberAdded;
    }

    public int getProgressCurrent() {
        return progressCurrent;
    }

    public int getProgressMax() {
        return progressMax;
    }

    public String getUsername() {
        return username;
    }

    public char[] getPassword() {
        return password;
    }

    public int lectureFichier() {
        BufferedReader lecteur;
        String temp;

        try {
            lecteur = new BufferedReader(new FileReader(fichier));

            while ((temp = lecteur.readLine()) != null) {
                classageLigneFichier(temp);
            }
        } catch (Exception e) {
            return 1;
        }

        sortGroupes();

        return 0;
    }

    private void classageLigneFichier(String alpha) {
        int[] tabIndex;
        String nom, temp;
        int nbIndex = 0;
        ArrayList<String> emails = new ArrayList<String>();

        nom = alpha.substring(0, alpha.indexOf(" "));

        temp = alpha.substring(alpha.indexOf(" "));
        temp = temp.trim();

        for (int i = 0; i < temp.length(); i++) {
            if (temp.charAt(i) == ',') {
                nbIndex++;
            }
        }
        tabIndex = new int[nbIndex];

        int indexNow = 0;
        for (int i = 0; i < temp.length(); i++) {
            if (temp.charAt(i) == ',') {
                tabIndex[indexNow] = i;
                indexNow++;
            }
        }

        for (int i = 0; i <= tabIndex.length; i++) {
            if (i == 0) {
                if (tabIndex.length == 0) {
                    emails.add(temp);
                } else {
                    emails.add(temp.substring(0, tabIndex[i]));
                }

            } else if (i == tabIndex.length) {
                emails.add(temp.substring(tabIndex[i - 1] + 1));
            } else {
                emails.add(temp.substring(tabIndex[i - 1] + 1, tabIndex[i]));
            }
        }

        listeGroupes.add(new Groupe(nom, emails));
    }

    public int miseAJour() {
        ArrayList<Groupe> listeGroupesToDelete = new ArrayList<Groupe>();
        ArrayList<Groupe> listeGroupesToAdd = new ArrayList<Groupe>();
        ArrayList<Membre> listeMembresToDelete = new ArrayList<Membre>();
        ArrayList<Membre> listeMembresToAdd = new ArrayList<Membre>();
        boolean groupePresent, membrePresent, noError;
        Random random = new Random();
        
        //Set la prgression pour la phase detection
        setProgressDetection();

        try {
            //Detection des groupes/membres a supprimer du serveur
            for (int i = 0; i < listeGroupesServeur.size(); i++) {
                fenetre.updateBar(progressCurrent, progressMax, "Analyse des groupes et membres...", listeGroupesServeur.get(i).getNomGroupe());
                groupePresent = false;

                for (int j = 0; j < listeGroupes.size(); j++) {
                    if (listeGroupes.get(j).getNomGroupe().equals(listeGroupesServeur.get(i).getNomGroupe())) {
                        groupePresent = true;

                        for (int k = 0; k < listeGroupesServeur.get(i).getEmailsGroupe().size(); k++) {
                            membrePresent = false;

                            for (int l = 0; l < listeGroupes.get(j).getEmailsGroupe().size(); l++) {
                                if (listeGroupes.get(j).getEmailsGroupe().get(l).equals(listeGroupesServeur.get(i).getEmailsGroupe().get(k))) {
                                    membrePresent = true;
                                }
                            }

                            if (!membrePresent) {
                                listeMembresToDelete.add(new Membre(listeGroupesServeur.get(i).getNomGroupe(), listeGroupesServeur.get(i).getEmailsGroupe().get(k)));
                            }
                        }
                    }
                }

                if (!groupePresent) {
                    listeGroupesToDelete.add(new Groupe(listeGroupesServeur.get(i).getNomGroupe(), null));
                }
                
                progressCurrent++;
            }

            //Detection des groupes/membres a ajouter au serveur
            for (int i = 0; i < listeGroupes.size(); i++) {
                fenetre.updateBar(progressCurrent, progressMax, "Analyse des groupes et membres...", listeGroupes.get(i).getNomGroupe());
                groupePresent = false;

                for (int j = 0; j < listeGroupesServeur.size(); j++) {
                    if (listeGroupesServeur.get(j).getNomGroupe().equals(listeGroupes.get(i).getNomGroupe())) {
                        groupePresent = true;

                        for (int k = 0; k < listeGroupes.get(i).getEmailsGroupe().size(); k++) {
                            membrePresent = false;

                            for (int l = 0; l < listeGroupesServeur.get(j).getEmailsGroupe().size(); l++) {
                                if (listeGroupesServeur.get(j).getEmailsGroupe().get(l).equals(listeGroupes.get(i).getEmailsGroupe().get(k))) {
                                    membrePresent = true;
                                }
                            }

                            if (!membrePresent) {
                                listeMembresToAdd.add(new Membre(listeGroupes.get(i).getNomGroupe(), listeGroupes.get(i).getEmailsGroupe().get(k)));
                            }
                        }
                    }
                }

                if (!groupePresent) {
                    listeGroupesToAdd.add(new Groupe(listeGroupes.get(i).getNomGroupe(), null));
                }
                
                progressCurrent++;
            }
            
            //Set la progression pour la phase creation des nouveaux elements
            setProgressCreation(listeMembresToDelete.size(), listeGroupesToDelete.size(), listeGroupesToAdd.size(), listeMembresToAdd.size());

            //Supprimer membres
            for (int i = 0; i < listeMembresToDelete.size(); i++) {
                for (int k = 0; k < 5; k++) {
                    fenetre.updateBar(progressCurrent, progressMax, "Suppression des membres...", listeMembresToDelete.get(i).getMemberId());
                    noError = true;

                    try {
                        myService.deleteMemberFromGroup(listeMembresToDelete.get(i).getMemberId(), listeMembresToDelete.get(i).getGroupId());
                    } catch (Exception e) {
                        noError = false;
                        Thread.sleep((long) (Math.pow(2000, k)) + random.nextInt(1000));
                    }

                    if (noError) {
                        k = 4;
                    } else if (!noError && k == 4) {
                        return 1;
                    }
                }
                
                progressCurrent++;
            }

            //Supprimer groupes
            for (int i = 0; i < listeGroupesToDelete.size(); i++) {
                for (int k = 0; k < 5; k++) {
                    fenetre.updateBar(progressCurrent, progressMax, "Suppression des groupes...", listeGroupesToDelete.get(i).getNomGroupe());
                    noError = true;

                    try {
                        myService.deleteGroup(listeGroupesToDelete.get(i).getNomGroupe());
                    } catch (Exception e) {
                        noError = false;
                        Thread.sleep((long) (Math.pow(2000, k)) + random.nextInt(1000));
                    }

                    if (noError) {
                        k = 4;
                    } else if (!noError && k == 4) {
                        return 1;
                    }
                }
                
                progressCurrent++;
            }

            //Ajouter groupes
            for (int i = 0; i < listeGroupesToAdd.size(); i++) {
                for (int k = 0; k < 5; k++) {
                    fenetre.updateBar(progressCurrent, progressMax, "Ajout des groupes...", listeGroupesToAdd.get(i).getNomGroupe());
                    noError = true;

                    try {
                        myService.createGroup(listeGroupesToAdd.get(i).getNomGroupe(), listeGroupesToAdd.get(i).getNomGroupe(), listeGroupesToAdd.get(i).getNomGroupe(), "Anyone");
                    } catch (Exception e) {
                        noError = false;
                        Thread.sleep((long) (Math.pow(2000, k)) + random.nextInt(1000));
                    }

                    if (noError) {
                        k = 4;
                    } else if (!noError && k == 4) {
                        return 1;
                    }
                }
                
                progressCurrent++;
            }

            //Ajouter membres
            for (int i = 0; i < listeMembresToAdd.size(); i++) {
                for (int k = 0; k < 5; k++) {
                    fenetre.updateBar(progressCurrent, progressMax, "Ajout des membres...", listeMembresToAdd.get(i).getMemberId());
                    noError = true;

                    try {
                        myService.addMemberToGroup(listeMembresToAdd.get(i).getGroupId(), listeMembresToAdd.get(i).getMemberId());
                    } catch (Exception e) {
                        noError = false;
                        Thread.sleep((long) (Math.pow(2000, k)) + random.nextInt(1000));
                    }

                    if (noError) {
                        k = 4;
                    } else if (!noError && k == 4) {
                        return 1;
                    }
                }
                
                progressCurrent++;
            }
            
            //Update finale de la barre
            fenetre.updateBar(progressCurrent, progressMax, "Finalisation...", "");
            
            //Reset de la liste du serveur
            retrieveGroups(false);
            
        } catch (Exception e) {
            return 1;
        }

        return 0;
    }

    public boolean setConnexion() {
        String passString = "";

        for (int i = 0; i < password.length; i++) {
            passString += String.valueOf(password[i]);
        }

        try {
            myService = new AppsGroupsService(username, passString, "Croesus.com", "Gestion Goggle Groups");
        } catch (Exception e) {
            return false;
        }

        return true;
    }

    public boolean retrieveGroups(boolean booting) {
        try {
            String nom;
            ArrayList<String> emails = new ArrayList<String>();
            GenericFeed groupFeed, memberFeed;
            
            listeGroupesServeur.clear();
            if (booting) {
                listeGroupes.clear();
            }

            groupFeed = myService.retrieveAllGroups();

            for (int i = 0; i < groupFeed.getEntries().size(); i++) {
                nom = groupFeed.getEntries().get(i).getId();
                memberFeed = myService.retrieveAllMembers(nom);

                for (int j = 0; j < memberFeed.getEntries().size(); j++) {
                    emails.add(memberFeed.getEntries().get(i).getId());
                }

                listeGroupesServeur.add(new Groupe(nom, emails));
                
                if (booting) {
                    listeGroupes.add(new Groupe(nom, emails));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }
    
    public boolean detecterGroupe(String nomGroupe) {
        boolean groupeDetecte = false;
        
        for (int i = 0; i < listeGroupes.size(); i++) {
            if (listeGroupes.get(i).getNomGroupe().equals(nomGroupe)) {
                groupeDetecte = true;
            }
        }
        
        return groupeDetecte;
    }
    
    public boolean deecterMembre(String nomGroupe, String emailMembre) {
        boolean membreDetecte = false;
        
        for (int i = 0; i < listeGroupes.size(); i++) {
            if (listeGroupes.get(i).getNomGroupe().equals(nomGroupe)) {
                for (int j = 0; j < listeGroupes.get(i).getEmailsGroupe().size(); j++) {
                    if (listeGroupes.get(i).getEmailsGroupe().get(j).equals(emailMembre)) {
                        membreDetecte = true;
                    }
                }
            }
        }
        
        return membreDetecte;
    }
}
